package com.example.webrtc.websocket;

import com.alibaba.fastjson.JSON;
import com.example.webrtc.model.WebRTCMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
@Component
@ServerEndpoint("/signaling")
public class SignalingWebSocket {
    // 存储所有在线用户的WebSocket会话
    private static final Map<String, Session> users = new ConcurrentHashMap<>();
    // 存储用户ID和名称的映射
    private static final Map<String, String> userNames = new ConcurrentHashMap<>();
    // 添加消息发送锁
    private static final Map<Session, ReentrantLock> sessionLocks = new ConcurrentHashMap<>();
    
    private String userId;

    @OnOpen
    public void onOpen(Session session) {
        sessionLocks.put(session, new ReentrantLock());
        log.info("新的WebSocket连接: {}", session.getId());
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        try {
            WebRTCMessage webRTCMessage = JSON.parseObject(message, WebRTCMessage.class);
            log.info("收到消息 from: {}, to: {}, type: {}", 
                webRTCMessage.getFrom(), 
                webRTCMessage.getTo(), 
                webRTCMessage.getType());

            switch (webRTCMessage.getType()) {
                case "join":
                    handleJoin(webRTCMessage, session);
                    break;
                case "chat":
                    log.info("转发聊天消息: {} -> {}", webRTCMessage.getFrom(), webRTCMessage.getTo());
                    forwardMessage(webRTCMessage);
                    break;
                case "whiteboard":
                    log.info("转发白板数据: {} -> {}, action: {}", 
                        webRTCMessage.getFrom(), 
                        webRTCMessage.getTo(),
                        webRTCMessage.getAction());
                    forwardMessage(webRTCMessage);
                    break;
                case "call-invitation":
                case "call-accepted":
                case "call-rejected":
                case "offer":
                case "answer":
                case "ice":
                case "call-ended":
                    forwardMessage(webRTCMessage);
                    break;
                case "leave":
                    handleLeave(webRTCMessage);
                    break;
                default:
                    log.warn("未知的消息类型: {}", webRTCMessage.getType());
            }
        } catch (Exception e) {
            log.error("处理消息时发生错误: {}", message, e);
        }
    }

    @OnClose
    public void onClose(Session session) {
        if (userId != null) {
            users.remove(userId);
            userNames.remove(userId);
            // 通知其他用户该用户已离开
            broadcastUserList();
        }
        sessionLocks.remove(session);
        log.info("WebSocket连接关闭: {}", session.getId());
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket错误", error);
    }

    private void handleJoin(WebRTCMessage message, Session session) {
        userId = message.getFrom();
        users.put(userId, session);
        userNames.put(userId, message.getName());
        
        log.info("用户加入: {}, 当前在线用户: {}", userId, userNames.keySet());
        
        // 发送当前在线用户列表给新用户
        sendUserList(session);
        // 广播新用户加入消息给其他用户
        broadcastUserList();
    }

    private void handleLeave(WebRTCMessage message) {
        String leavingUserId = message.getFrom();
        Session session = users.get(leavingUserId);
        if (session != null) {
            users.remove(leavingUserId);
            userNames.remove(leavingUserId);
            broadcastUserList();
        }
    }

    private void forwardMessage(WebRTCMessage message) {
        Session targetSession = users.get(message.getTo());
        if (targetSession != null && targetSession.isOpen()) {
            log.info("正在转发消息 type: {} from: {} to: {}", 
                message.getType(), 
                message.getFrom(), 
                message.getTo());
            sendMessageToSession(targetSession, message);
        } else {
            log.warn("目标用户不在线或会话已关闭: {}", message.getTo());
        }
    }

    private void sendUserList(Session session) {
        WebRTCMessage message = new WebRTCMessage();
        message.setType("users");
        message.setData(userNames);
        sendMessageToSession(session, message);
    }

    private void broadcastUserList() {
        WebRTCMessage message = new WebRTCMessage();
        message.setType("users");
        message.setData(userNames);
        
        users.values().forEach(session -> {
            sendMessageToSession(session, message);
        });
    }

    private void sendMessageToSession(Session session, WebRTCMessage message) {
        if (session == null || !session.isOpen()) {
            return;
        }

        ReentrantLock lock = sessionLocks.get(session);
        if (lock != null) {
            lock.lock();
            try {
                String messageJson = JSON.toJSONString(message);
                session.getBasicRemote().sendText(messageJson);
            } catch (IOException e) {
                log.error("发送消息失败", e);
            } finally {
                lock.unlock();
            }
        }
    }
} 